/*
 * Copyright (C) 2011 by Anton Novikau
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.googlecode.gplaces.core;

import android.app.Activity;
import android.app.Application;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Share Places application implementation used for caching all In-Progress
 * async tasks. Such a solution protects loosing AsyncTask references on
 * activity recreation when it's killed by TaskManager or device configuration
 * was changed.
 * 
 * @author Anton Novikov
 */
public class GplacesApp extends Application {

    private Map<String, List<SafeAsyncTask<?, ?, ?>>> activityTaskCache;

    /**
     * {@inheritDoc}
     */
    @Override
    public void onCreate() {
        super.onCreate();
        this.activityTaskCache = new HashMap<String, List<SafeAsyncTask<?, ?, ?>>>();
    }

    /**
     * Removes async task from cache when it is finished or canceled.
     * 
     * @param task async task instance being removed
     */
    public void removeTask(SafeAsyncTask<?, ?, ?> task) {
        for (Entry<String, List<SafeAsyncTask<?, ?, ?>>> entry : activityTaskCache.entrySet()) {
            List<SafeAsyncTask<?, ?, ?>> tasks = entry.getValue();
            for (int i = 0; i < tasks.size(); i++) {
                if (tasks.get(i) == task) {
                    tasks.remove(i);
                    break;
                }
            }

            if (tasks.isEmpty()) {
                activityTaskCache.remove(entry.getKey());
                return;
            }
        }
    }

    /**
     * Adds task to cache when it is started.
     * 
     * @param activity activity instance to attach task to
     * @param task task being cached
     */
    public void addTask(Activity activity, SafeAsyncTask<?, ?, ?> task) {
        String key = activity.getClass().getName();
        List<SafeAsyncTask<?, ?, ?>> tasks = activityTaskCache.get(key);
        if (tasks == null) {
            tasks = new ArrayList<SafeAsyncTask<?, ?, ?>>();
            activityTaskCache.put(key, tasks);
        }

        tasks.add(task);
    }

    /**
     * Detaching activity from async task when it is going to be recreated.
     * 
     * @param activity activity being detached
     */
    public void detach(Activity activity) {
        List<SafeAsyncTask<?, ?, ?>> tasks = activityTaskCache.get(activity.getClass().getName());
        if (tasks != null) {
            for (SafeAsyncTask<?, ?, ?> task : tasks) {
                task.setActivity(null);
            }
        }
    }

    /**
     * Attaching activity to async task when it is restored the state.
     * 
     * @param activity activit being attached
     */
    public void attach(Activity activity) {
        List<SafeAsyncTask<?, ?, ?>> tasks = activityTaskCache.get(activity.getClass().getName());
        if (tasks != null) {
            for (SafeAsyncTask<?, ?, ?> task : tasks) {
                task.setActivity(activity);
            }
        }
    }
}
